home *** CD-ROM | disk | FTP | other *** search
- /*
- * update the password file and (if necessary)
- * any associated DBM database
- */
- #include "passwd.h"
- #include <signal.h>
- #ifdef YPPASSWD
- #include <rpcsvc/yppasswd.h>
- #endif
- #ifdef DBMLIB
- # include <dbm.h>
- #endif
-
- #ifdef SYSV_PWFUNC
- /*
- * library function
- */
- extern struct passwd *fgetpwent(); /* get password entry from any file */
- #endif
-
- /*
- * some definitions
- */
- #define PF_PLATE "./ptmpXXXXX" /* original temporary file */
- #define PF_TEMP "./ptmp" /* lock file */
- #define PW_CANTLOCK -1 /* error code -- locking failed */
- #define PW_CANTOPEN -2 /* error code -- open failed */
- #define PW_CANTRENAME -3 /* error code -- rename failed */
- #define PW_NOCHANGE -4 /* error code -- no passwd entry */
-
- /*
- * global variables
- */
- char *pf_name = "/etc/passwd"; /* password file name */
- char *pf_tnam; /* name of temporary file */
- FILE *pf_fp; /* pointer to real password file */
- FILE *pf_tfp; /* pointer to temporary file */
- int pf_errno; /* error number */
-
- /*
- * library functions
- */
- extern char *mktemp(); /* makes a temp file name */
-
- #ifndef NOSETPWFILE
- /*
- * change the password file's name
- */
- name_pwd(name)
- char *name;
- {
- /*
- * reassociate the name
- */
- pf_name = name;
- }
- #endif
-
- check_age(p)
- struct passwd *p;
- {
- #ifdef AGE_FIELD
- long aging, now, a64l(), time();
- int min, max;
- if (*p->pw_age == NULL)
- return(1);
- aging = a64l(p->pw_age);
- now = time(0L) / (60 * 60 * 24 * 7);
- max = aging & 077;
- min = (aging >> 6) & 077;
- aging >>= 12;
- return(max >= min && aging + min <= now);
- #else
- return(1);
- #endif
- }
-
- update_pwd(p)
- struct passwd *p; /* new password structure */
- {
- char nbuf[BUFSIZ]; /* buffer for passwords being read */
- char obuf[BUFSIZ]; /* buffer for new entry */
- register char *q, *s; /* used for quick name comparison */
- int retval = PW_NOCHANGE; /* return value */
- #ifdef DBMLIB
- union {
- int i; /* as an integer */
- char c[1]; /* as a character */
- } itoc; /* maps integer into char storage */
- datum key; /* key data is to be stored under */
- datum newrec; /* record to be stored */
- #endif
-
- /*
- * disable ALL signals at this point
- */
- sigoff();
-
- /*
- * open the temporary password file
- */
- umask(022);
- pf_tnam = mktemp(PF_PLATE);
- if ((pf_tfp = fopen(pf_tnam, "w")) == FI_NULL){
- pf_errno = errno;
- retval = PW_CANTOPEN;
- goto cantlock;
- }
-
- /*
- * lock the password file
- */
- if (link(pf_tnam, PF_TEMP) < 0){
- pf_errno = errno;
- retval = PW_CANTLOCK;
- goto cantlock;
- }
-
- /*
- * copy the new password structure
- */
- #ifdef AGE_FIELD
- { long aging, thischange, a64l(), time(); char *l64a();
- aging = a64l(p->pw_age);
- thischange = time(0L) / (60 * 60 * 24 * 7);
- aging = (thischange<<12)|(aging&07777);
- p->pw_age = l64a(aging);
- SPRINTF(obuf, "%s:%s,%s:%d:%d:%s:%s:%s\n",
- p->pw_name, p->pw_passwd, p->pw_age, p->pw_uid,
- p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);
- }
- #else
- SPRINTF(obuf, "%s:%s:%d:%d:%s:%s:%s\n",
- p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid,
- p->pw_gecos, p->pw_dir, p->pw_shell);
- #endif
-
- /*
- * open the password file
- */
- if ((pf_fp = fopen(pf_name, "r")) == FI_NULL){
- pf_errno = errno;
- retval = PW_CANTOPEN;
- goto getout;
- }
-
-
- /*
- * copy the password file into the temporary one
- */
- while(fgets(nbuf, BUFSIZ, pf_fp) != NULL){
- for(s = nbuf, q = p->pw_name; *s && *s != ':'; s++, q++)
- if (*s != *q)
- break;
- if (*s == ':' && *q == '\0') {
- fputs(obuf, pf_tfp);
- retval = 0;
- } else
- fputs(nbuf, pf_tfp);
- }
- if (retval == PW_NOCHANGE) {
- #ifdef YPPASSWD
- if(yppasswd(oldpassword, p) == 0) {
- retval = 0;
- }
- #endif
- goto getout;
- }
-
- /*
- * close the temporary file and the real one
- */
- (void) fclose(pf_tfp);
- pf_tfp = FI_NULL;
- (void) fclose(pf_fp);
- pf_fp = FI_NULL;
-
- /*
- * now relink; note the lock file is still there
- */
- #ifdef RENAME
- if (RENAME(pf_tnam, pf_name) < 0){
- #else
- if (unlink(pf_name) >= 0
- && link(pf_tnam, pf_name) >= 0
- && unlink(pf_tnam) >= 0){
- #endif
- pf_errno = errno;
- retval = PW_CANTRENAME;
- }
-
- #ifdef DBMLIB
- /*
- * see if there is a corresponding dbm file
- */
- if (dbminit(pf_name) >= 0){
- register int i; /* counter in a for loop */
- /*
- * there is; make the new datum in nbuf
- */
- q = nbuf;
- for(s = p->pw_name; *q++ = *s++; ); /* pw_name */
- for(s = p->pw_passwd; *q++ = *s++; ); /* pw_passwd */
- itoc.i = p->pw_uid; /* pw_uid */
- for(i = 0; i < sizeof(int); i++)
- *q++ = itoc.c[i];
- itoc.i = p->pw_gid; /* pw_gid */
- for(i = 0; i < sizeof(int); i++)
- *q++ = itoc.c[i];
- itoc.i = p->pw_quota; /* pw_quota */
- for(i = 0; i < sizeof(int); i++)
- *q++ = itoc.c[i];
- for(s = p->pw_comment; *q++ = *s++; ); /* pw_comment */
- for(s = p->pw_gecos; *q++ = *s++; ); /* pw_gecos */
- for(s = p->pw_dir; *q++ = *s++; ); /* pw_dir */
- for(s = p->pw_shell; *q++ = *s++; ); /* pw_shell */
- /*
- * now the size of the data
- */
- newrec.dptr = nbuf;
- newrec.dsize = q - nbuf;
- /*
- * store it under the UID and the name
- */
- itoc.i = p->pw_uid;
- key.dptr = itoc.c; key.dsize = sizeof(int);
- store(key, newrec);
- key.dptr = p->pw_name; key.dsize = strlen(p->pw_name);
- store(key, newrec);
- }
- #endif
-
- getout:
- /*
- * Only remove lock file if this program obtained it
- */
- (void) unlink(PF_TEMP);
- cantlock:
- /*
- * some clean up
- */
- if (pf_tfp != FI_NULL)
- (void) fclose(pf_tfp);
- if (pf_fp != FI_NULL)
- (void) fclose(pf_fp);
- (void) unlink(pf_tnam);
-
- /*
- * re-enable ALL signals at this point
- */
- sigon();
-
- /*
- * good!
- */
- return(retval);
- }
-
- /*
- * get a name; built on other library routines
- */
- struct passwd *mgpwnam(name)
- char *name; /* name being looked for */
- {
- #ifdef FGETPWENT
- register struct passwd *p; /* points to returning structure */
- /*
- * open the password file
- */
- if ((pf_fp = fopen(pf_name, "r")) == FI_NULL){
- perror(pf_name);
- exit(1);
- }
- /*
- * scan the file looking for the right line
- */
- while((p = FGETPWENT(pf_fp)) != PW_NULL)
- if (strcmp(p->pw_name, name) == 0)
- break;
-
- /*
- * close the file and return the right structure
- */
- (void) fclose(pf_fp);
- return(p);
- #else
- #ifdef SETPWFILE
- register struct passwd *p; /* points to returning structure */
- /*
- * set the password file name
- */
- SETPWFILE(pf_name);
- /*
- * get the required structure
- */
- p = getpwnam(name);
- /*
- * close the file and return the data
- */
- endpwent();
- return(p);
- #else
- return(getpwnam(name));
- #endif
- #endif
- }
-
- /*
- * get a uid; built on other library routines
- */
- struct passwd *mgpwuid(uid)
- int uid; /* uid being looked for */
- {
- #ifdef FGETPWENT
- register struct passwd *p; /* points to returning structure */
- /*
- * open the password file
- */
- if ((pf_fp = fopen(pf_name, "r")) == FI_NULL){
- perror(pf_name);
- exit(1);
- }
- /*
- * scan the file looking for the right line
- */
- while((p = FGETPWENT(pf_fp)) != PW_NULL)
- if (uid == p->pw_uid)
- break;
-
- /*
- * close the file and return the right structure
- */
- (void) fclose(pf_fp);
- return(p);
- #else
- #ifdef SETPWFILE
- register struct passwd *p; /* points to returning structure */
- /*
- * set the password file name
- */
- SETPWFILE(pf_name);
- /*
- * get the required structure
- */
- p = getpwuid(uid);
- /*
- * close the file and return the data
- */
- endpwent();
- return(p);
- #else
- return(getpwuid(uid));
- #endif
- #endif
- }
-
-